from celery import current_task
from celery import task
from cvirt.common import utils
from cvirt.tasks import TaskWrap

API = utils.cnode_import_class('cvirt.cnode.vm.api.API')
if API: API.init()

import logging
#add your task here
from cvirt.common.constant import TaskAction
from cvirt.manager.models import TaskDetail

LOG = logging.getLogger(__name__)

@TaskWrap
@task()
def create_vm(instance,snapshot=False, needlaunch=False,uuid=None):

    current_task.update_state(state="building")

    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.CREATE_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)

    return API.create(instance,snapshot=snapshot, needlaunch=needlaunch)

@TaskWrap
@task()
def shutdown_vm(instance,is_soft=False,uuid=None):
    current_task.update_state(state="shutdowning")

    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.SHUTDOWN_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)
    try:
        inst = API.shutdown(instance,is_soft=is_soft)
    except:
        # no need to update statues ,djcelery will update it
        raise

    return inst

@TaskWrap
@task()
def start_vm(instance,uuid=None):
    current_task.update_state(state="starting")

    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.START_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)
    try:
        inst = API.start(instance)
    except:
        # no need to update statues ,djcelery will update it
        raise

    return inst

@TaskWrap
@task()
def reboot_vm(instance,is_soft=False,uuid=None):
    current_task.update_state(state="rebooting")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.REBOOT_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)

    try:
        inst = API.reboot(instance,is_soft=is_soft)
    except:
        # current_task.update_state(state="error")
        # no need to update statues ,djcelery will update it
        raise

    return inst

@TaskWrap
@task()
def pause_vm(instance,uuid=None):
    current_task.update_state(state="rebooting")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.PAUSE_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)

    try:
        inst = API.pause(instance)
    except:
        # current_task.update_state(state="error")
        # no need to update statues ,djcelery will update it
        raise

    return inst


@TaskWrap
@task()
def unpause_vm(instance,uuid=None):
    current_task.update_state(state="rebooting")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.UNPAUSE_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)

    try:
        inst = API.unpause(instance)
    except:
        # current_task.update_state(state="error")
        # no need to update statues ,djcelery will update it
        raise

    return inst

@TaskWrap
@task()
def hibernate_vm(instance,uuid=None):
    current_task.update_state(state="rebooting")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.HIBERNATE_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)

    try:
        inst = API.hibernate(instance)
    except:
        # current_task.update_state(state="error")
        # no need to update statues ,djcelery will update it
        raise

    return inst

@TaskWrap
@task()
def update_vm(instance,snapshot=False,uuid=None):
    current_task.update_state(state="updating")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.UPDATE_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)

    try:
        is_update = API.update(instance,snapshot=snapshot)
    except:
        #current_task.update_state(state="error")
        # no need to update statues ,djcelery will update it
        raise

    return is_update


@TaskWrap
@task()
def update_disk(vdisk,snapshot=False,uuid=None):
    current_task.update_state(state="updating")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.UPDATE_DISK,type=TaskAction.VM,
                              target=vdisk.instance.name,meta_id=current_task.request.id)

    try:
        API.update(vdisk.instance)
    except:
        #current_task.update_state(state="error")
        # no need to update statues ,djcelery will update it
        raise

@TaskWrap
@task()
def save_as_template(vdisk,image,uuid=None):
    current_task.update_state(state="snapshoting")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.SAVE_TEMPLATE,type=TaskAction.VM,
                              target=vdisk.instance.name,meta_id=current_task.request.id)

    try:
        API.save_as_template(vdisk,image)
    except:
        image.delete()
        #current_task.update_state(state="error")
        # no need to update statues ,djcelery will update it
        raise

@TaskWrap
@task()
def snapshot_vm(instance,snapshot,uuid=None):
    current_task.update_state(state="snapshoting")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.SNAPSHOT_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)

    try:
        API.snapshot(instance,snapshot)
    except:
        snapshot.delete()
        #current_task.update_state(state="error")
        # no need to update statues ,djcelery will update it
        raise


@TaskWrap
@task()
def snapshot_restore(instance,snapshot,uuid=None):
    current_task.update_state(state="snapshoting")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.RESTORE_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)
    try:
        is_update = API.snapshot_restore(instance,snapshot)
    except:
        # current_task.update_state(state="error")
        # no need to update statues ,djcelery will update it
        raise

    return is_update

@TaskWrap
@task()
def snapshot_delete(instance,snapshot,uuid=None):
    current_task.update_state(state="snapshoting")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.DELETE_SNAP,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)
    try:
        API.snapshot_delete(instance,snapshot)
        snapshot.delete()
    except:
        # current_task.update_state(state="error")
        # no need to update statues ,djcelery will update it
        raise


@TaskWrap
@task()
def delete_vm(instance,uuid=None):
    current_task.update_state(state="deleting")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.DESTORY_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)

    try:
        is_delete = API.destroy(instance)
        if is_delete:
            LOG.debug("deleting vm successful,we can delete instance model")
            instance.delete()
    except:
        raise

    return is_delete


@TaskWrap
@task()
def delete_disk(vdisk,cleanup=False,uuid=None):
    current_task.update_state(state="deleting")
    target = vdisk.instance.name if vdisk.instance else vdisk.name
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.DELETE_DISK,type=TaskAction.VM,
                              target=target,meta_id=current_task.request.id)
    try:
        is_delete = API.delete_vdisk(vdisk,cleanup=cleanup)
        if is_delete:
            LOG.debug("deleting disk successful")

    except:
        raise

    return is_delete


@TaskWrap
@task()
def update_cdrom(vdisk,uuid=None):
    current_task.update_state(state="updating")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.UPDATE_CDROM,type=TaskAction.VM,
                              target=vdisk.instance.name,meta_id=current_task.request.id)
    try:
         API.update_cdrom(vdisk)
    except:
        raise


@TaskWrap
@task()
def add_disk(vdisk,uuid=None):
    current_task.update_state(state="updating")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.ADD_DISK,type=TaskAction.VM,
                              target=vdisk.instance.name,meta_id=current_task.request.id)
    try:
         API.update(vdisk.instance)
    except:
        vdisk.delete()
        raise


@TaskWrap
@task()
def apply_sgroup(sgroup,interfaces=[],uuid=None):
    try:
        return API.apply_sgroup(sgroup,interfaces)
    except:
        raise


@TaskWrap
@task()
def update_sgroup(sgroup,uuid=None):
    try:
        return API.update_sgroup(sgroup)
    except:
        raise


@TaskWrap
@task()
def remove_sgroup(sgroup,interfaces,uuid=None):
    try:
        API.remove_sgroup(sgroup,interfaces)
        sgroup.delete()
    except:
        raise

# @TaskWrap
# @task()
# def vm_status(inst,uuid=None):
#     try:
#         return API.status(inst)
#     except:
#         raise

@TaskWrap
@task()
def delete_template(path,uuid=None):
    try:
        return API.delete_template(path)
    except:
        raise


@TaskWrap
@task()
def migrate(instance,dest,offline=False,timeout=None,bandwidth=0, uuid=None):
    current_task.update_state(state="migrating")
    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.MIGRATE_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)
    try:
        API.migrate(instance,dest.ip,offline=offline,timeout=timeout,bandwidth=bandwidth)
        post_migrate.call(instance.host.host_name,instance)
        instance.update(dict(host=dest))
    except:
        raise

@TaskWrap
@task()
def pre_migrate(instance,uuid=None):
    try:
        API.pre_migrate(instance)
    except:
        raise

@TaskWrap
@task()
def post_migrate(instance,uuid=None):
    try:
        API.post_migrate(instance)
    except:
        raise

@TaskWrap
@task()
def clone_vm(disk_relattion,instance,originvm, fullclone,uuid=None):

    current_task.update_state(state="building")

    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.CLONE_VM,type=TaskAction.VM,
                              target=instance.name,meta_id=current_task.request.id)

    return API.clone(disk_relattion,instance,originvm, fullclone=fullclone)


@TaskWrap
@task()
def client_start_vm(instance,uuid=None):
    current_task.update_state(state="starting")

    TaskDetail.create_if_not_exsist(uuid,name=TaskAction.LOGIN_VM,type=TaskAction.CLIENT,
                              target=instance.name,meta_id=current_task.request.id)
    try:
        inst = API.start(instance)
    except:
        # no need to update statues ,djcelery will update it
        raise

    return inst